package com.xugui.learn.pay.strategy;

import com.xugui.learn.pay.pojo.constant.Constants;
import com.xugui.learn.pay.pojo.request.PayRequest;
import com.xugui.learn.pay.pojo.request.RefundRequest;
import com.xugui.learn.pay.pojo.response.CloseResponse;
import com.xugui.learn.pay.pojo.response.PayResponse;
import com.xugui.learn.pay.pojo.response.QueryResponse;
import com.xugui.learn.pay.pojo.response.RefundResponse;
import lombok.extern.slf4j.Slf4j;

/**
 * 抽象支付策略
 */
@Slf4j
public abstract class AbstractPayStrategy implements PayStrategy {

    /**
     * 统一支付接口
     *
     * @param request 支付请求参数
     * @return 支付响应参数
     */
    @Override
    public PayResponse pay(PayRequest request) {
        try {
            log.info("开始支付，渠道：{}，订单号：{}", getPayChannel().getName(), request.getOrderNo());
            return doPay(request);
        } catch (Exception e) {
            log.error("支付异常，渠道：{}，订单号：{}", getPayChannel().getName(), request.getOrderNo(), e);
            return PayResponse.failure(Constants.OPERATE_ERROR_MSG, "支付处理异常：" + e.getMessage());
        }
    }

    /**
     * 查询订单
     *
     * @param request 支付请求参数
     * @return 查询订单响应参数
     */
    @Override
    public QueryResponse queryOrder(PayRequest request) {
        try {
            log.info("查询订单，渠道：{}，订单号：{}", getPayChannel().getName(), request.getOrderNo());
            return doQueryOrder(request);
        } catch (Exception e) {
            log.error("查询订单异常，渠道：{}，订单号：{}", getPayChannel().getName(), request.getOrderNo(), e);
            return QueryResponse.failure(Constants.OPERATE_ERROR_MSG, "查询订单异常：" + e.getMessage());
        }
    }

    /**
     * 关闭订单
     *
     * @param request 支付请求参数
     * @return 关闭订单响应参数
     */
    @Override
    public CloseResponse close(PayRequest request) {
        try {
            log.info("关闭订单，渠道：{}，订单号：{}", getPayChannel().getName(), request.getOrderNo());
            return doClose(request);
        } catch (Exception e) {
            log.error("关闭订单异常，渠道：{}，订单号：{}", getPayChannel().getName(), request.getOrderNo(), e);
            return CloseResponse.failure(Constants.OPERATE_ERROR_MSG, "关闭订单异常：" + e.getMessage());
        }
    }

    /**
     * 退款
     *
     * @param request 退款请求参数
     * @return 退款响应参数
     */
    @Override
    public RefundResponse refund(RefundRequest request) {
        try {
            log.info("开始退款，渠道：{}，退款单号：{}", getPayChannel().getName(), request.getRefundNo());
            return doRefund(request);
        } catch (Exception e) {
            log.error("退款异常，渠道：{}，退款单号：{}", getPayChannel().getName(), request.getRefundNo(), e);
            return RefundResponse.failure(Constants.OPERATE_ERROR_MSG, "退款处理异常：" + e.getMessage());
        }
    }

    /**
     * 退款查询
     *
     * @param request 退款请求参数
     * @return 退款响应参数
     */
    @Override
    public RefundResponse queryRefund(RefundRequest request) {
        try {
            log.info("开始退款查询，渠道：{}，退款单号：{}", getPayChannel().getName(), request.getRefundNo());
            return doQueryRefund(request);
        } catch (Exception e) {
            log.error("退款查询异常，渠道：{}，退款单号：{}", getPayChannel().getName(), request.getRefundNo(), e);
            return RefundResponse.failure(Constants.OPERATE_ERROR_MSG, "退款查询处理异常：" + e.getMessage());
        }
    }

    /**
     * 抽象方法，子类实现具体支付逻辑
     *
     * @param request 支付请求参数
     * @return 支付响应参数
     */
    protected abstract PayResponse doPay(PayRequest request);

    /**
     * 抽象方法，子类实现具体查询订单逻辑
     *
     * @param request 支付请求参数
     * @return 查询订单响应参数
     */
    protected abstract QueryResponse doQueryOrder(PayRequest request);

    /**
     * 抽象方法，子类实现具体关闭订单逻辑
     *
     * @param request 支付请求参数
     * @return 关闭订单响应参数
     */
    protected abstract CloseResponse doClose(PayRequest request);

    /**
     * 抽象方法，子类实现具体退款逻辑
     *
     * @param request 退款请求参数
     * @return 退款响应参数
     */
    protected abstract RefundResponse doRefund(RefundRequest request);

    /**
     * 抽象方法，子类实现具体退款查询逻辑
     *
     * @param request 退款查询请求参数
     * @return 退款查询响应参数
     */
    protected abstract RefundResponse doQueryRefund(RefundRequest request);

}